﻿using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace HttpClientSample
{
    public class HttpClientSamples : IDisposable
    {
        //请求地址：这里改成你自己的key
        private const string NorthwindUrl = "http://services.data.org/Northwind/Northwind.svc/Regions";
        private const string IncorrectUrl = "http://services.data.org/Northwind1/Northwind.svc/Regions";

        //实例化一个私有HttpClient，以实现重用
        //该HttpClient线程安全，一个HttpClient可以用于处理多个请求
        //HttpClient每个请求都维护它自己的线程池，所以HttpClient实例之间的请求会被隔离
        private HttpClient _httpClient;
        public HttpClient HttpClient => _httpClient ?? (_httpClient = new HttpClient());


        private HttpClient _httpClientWithMessageHandler;
        public HttpClient HttpClientWithMessageHandler => _httpClientWithMessageHandler ?? (_httpClientWithMessageHandler = new HttpClient(new SampleMessageHandler("error")));

        public async Task GetDataSimpleAsync()
        {
            //对GetAsync（）的调用返回HttpResponseMessage对象。
            //HttpResponseMessage对象对象包含标题、状态和内容
            HttpResponseMessage response = await HttpClient.GetAsync(NorthwindUrl);
            
            //检查响应属性IsSuccessStatusCode，可以判断请求是否成功
            if (response.IsSuccessStatusCode)
            {
                //输出状态码，状态码说明短语
                Console.WriteLine($"Response Status Code: {(int)response.StatusCode} {response.ReasonPhrase}");
              
                //把返回内容检索为字符串
                string responseBodyAsText = await response.Content.ReadAsStringAsync();

                //输出字符串的长度及字符
                Console.WriteLine($"Received payload of {responseBodyAsText.Length} characters");
                Console.WriteLine();
                Console.WriteLine(responseBodyAsText);
            }
        }

        public async Task GetDataAdvancedAsync()
        {
            //设置请求参数，默认Get请求是默认请求。
            var request = new HttpRequestMessage(HttpMethod.Get, NorthwindUrl);
            //使用Get方法请求目标地址
            HttpResponseMessage response = await HttpClient.SendAsync(request);
          
            //检查响应属性IsSuccessStatusCode，成功后读取响应内容
            if (response.IsSuccessStatusCode)
            {
                //输出状态码，状态码说明短语
                Console.WriteLine($"Response Status Code: {(int)response.StatusCode} {response.ReasonPhrase}");
                string responseBodyAsText = await response.Content.ReadAsStringAsync();
                Console.WriteLine($"Received payload of {responseBodyAsText.Length} characters");
                Console.WriteLine();
                Console.WriteLine(responseBodyAsText);
            }
        }
        /// <summary>
        /// 带抛出异常
        /// </summary>
        /// <returns></returns>
        public async Task GetDataWithExceptionsAsync()
        {
            
            try
            {
                //设置请求头部默认键值对响应类型，要求响应内容是json格式
                HttpClient.DefaultRequestHeaders.Add("Accept", "application/json;odata=verbose");
                //显示默认响应头
                ShowHeaders("Request Headers:", HttpClient.DefaultRequestHeaders);
                //异步Get请求目标地址
                HttpResponseMessage response = await HttpClient.GetAsync(IncorrectUrl);
              
                //HttpClient类的GetAsync方法失败，默认情况下不产生异常
                //调用EnsureSuccessStatusCode可以检查IsSuccessStatusCode是否为False，如果是抛出异常
                response.EnsureSuccessStatusCode();
                //输出响应头部
                ShowHeaders("Response Headers:", response.Headers);

                //输出响应状态码及对应短语
                Console.WriteLine($"Response Status Code: {response.StatusCode} {response.ReasonPhrase}");
                //异步读取响应数据
                string responseBodyAsText = await response.Content.ReadAsStringAsync();
                
                //获取响应数据长度
                Console.WriteLine($"Received payload of {responseBodyAsText.Length} characters");
                Console.WriteLine();
                Console.WriteLine(responseBodyAsText);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"{ex.Message}");
            }
        }

        //带请求头的异步数据请求，与上例同
        public async Task GetDataWithHeadersAsync()
        {
            try
            {

                HttpClient.DefaultRequestHeaders.Add("Accept", "application/json;odata=verbose");
                ShowHeaders("Request Headers:", HttpClient.DefaultRequestHeaders);

                HttpResponseMessage response = await HttpClient.GetAsync(NorthwindUrl);
                
                response.EnsureSuccessStatusCode();

                ShowHeaders("Response Headers:", response.Headers);

                Console.WriteLine($"Response Status Code: {(int)response.StatusCode} {response.ReasonPhrase}");
                string responseBodyAsText = await response.Content.ReadAsStringAsync();
                Console.WriteLine($"Received payload of {responseBodyAsText.Length} characters");
                Console.WriteLine();
                Console.WriteLine(responseBodyAsText);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"{ex.Message}");
            }
        }

        /// <summary>
        /// 遍历输出头部信息，请求头响应头都是一个格式，含键值对结构，通用
        /// </summary>
        /// <param name="title"></param>
        /// <param name="headers"></param>
        public void ShowHeaders(string title, HttpHeaders headers)
        {
            Console.WriteLine(title);
            foreach (var header in headers)
            {
                string value = string.Join(" ", header.Value);
                Console.WriteLine($"Header: {header.Key} Value: {value}");
            }
            Console.WriteLine();
        }

        /// <summary>
        /// 自定义请求
        /// 创建一个新的HTTPClient，通过构造函数注入处理程序，利用重写
        /// </summary>
        /// <returns></returns>
        public async Task GetDataWithMessageHandlerAsync()
        {
            try
            {
                HttpClientWithMessageHandler.DefaultRequestHeaders.Add("Accept", "application/json;odata=verbose");
                ShowHeaders("Request Headers:", HttpClientWithMessageHandler.DefaultRequestHeaders);

                HttpResponseMessage response = await HttpClientWithMessageHandler.GetAsync(NorthwindUrl);
                response.EnsureSuccessStatusCode();

                ShowHeaders("Response Headers:", response.Headers);

                Console.WriteLine($"Response Status Code: {(int)response.StatusCode} {response.ReasonPhrase}");
                string responseBodyAsText = await response.Content.ReadAsStringAsync();
                Console.WriteLine($"Received payload of {responseBodyAsText.Length} characters");
                Console.WriteLine();
                Console.WriteLine(responseBodyAsText);

            }
            catch (Exception ex)
            {
                Console.WriteLine($"{ex.Message}");
            }
        }

        //释放资源
        public void Dispose()
        {
            HttpClient?.Dispose();
            HttpClientWithMessageHandler?.Dispose();
        }
    }
}
